﻿using Dapper;
using DataBaseFactory;
using StudentManagement.Model.Entitys;
using StudentManagement.Tools;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;

namespace StudentManagement.Repository
{

    /// <summary>
    /// 仓储的基类
    /// </summary>
    /// <typeparam name="T">实体</typeparam>
    /// <typeparam name="KeyT">实体的主键类型</typeparam>
    public class RepositoryBase<T, KeyT> : CommonRepositoryBase where T : EntityBase<KeyT>
    {
        /// <summary>
        /// 数据库的表名
        /// </summary>
        protected readonly string DbTableName = StringTransition.TrimEnd(typeof(T).Name, "Entity");


        #region 数据库操作

        /// <summary>
        /// 查询列表
        /// </summary>
        protected virtual List<T> QueryList(string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
        {
            return Connection.Query<T>(sql, param, transaction, buffered, commandTimeout, commandType).ToList();
        }

        /// <summary>
        /// 返回符合条件的第一个实体，没有则返回默认值
        /// </summary>
        protected virtual T QueryFirstOrDefault(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            return Connection.QueryFirstOrDefault<T>(sql, param, transaction, commandTimeout, commandType);
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <returns>t1为实体集合，t2为总条数</returns>
        protected virtual Tuple<List<T>, int> QueryPagingList(string sql, int limit, int page, string orderByColumn, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
        {
            return QueryPagingList<T>(sql, limit, page, orderByColumn, param, transaction, buffered, commandTimeout, commandType);
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <returns>t1为实体集合，t2为总条数</returns>
        protected virtual Tuple<List<QT>, int> QueryPagingList<QT>(string sql, int limit, int page, string orderByColumn, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
        {
            string countSql = new System.Text.RegularExpressions.Regex(@"(?<=select)([\s\S]*)?(?=from)", System.Text.RegularExpressions.RegexOptions.IgnoreCase).Replace(sql, " Count(*) ");
            //获取总条数
            var count = Connection.ExecuteScalar(countSql, param, transaction, commandTimeout, commandType);
            string sqlSon = $" ORDER BY {orderByColumn} OFFSET {(page - 1) * limit} ROW FETCH NEXT {limit} ROWS ONLY";
            //分页查询
            var data = Connection.Query<QT>($"{sql}{sqlSon}", param, transaction, buffered, commandTimeout, commandType).ToList();
            //返回分页后的数据和总条数
            return new Tuple<List<QT>, int>(data, (int)count);
        }

        /// <summary>
        /// 查询条件是否存在数据
        /// </summary>
        /// <param name="whereString">条件字符串</param>
        /// <returns></returns>
        protected virtual bool QueryIsExist(string whereString, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            return Connection.QueryFirstOrDefault<bool>(
                $"isnull((select top 1 1 from [{DbTableName}] where {whereString}),0)",
                param,
                transaction,
                commandTimeout,
                commandType
                );
        }

        #endregion


        #region 资源释放

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!m_disposed)
            {
                if (disposing)
                {
                    // 释放托管资源
                }

                // 释放非托管资源
                ConnectionFactory.RemoveConnection(dbType);
                m_disposed = true;
            }
        }

        ~RepositoryBase()
        {
            Dispose(false);
        }

        private bool m_disposed;

        #endregion
    }

    /// <summary>
    /// 实体主键为int时的基类
    /// </summary>
    /// <typeparam name="T">实体</typeparam>
    public class RepositoryBase<T> : RepositoryBase<T, int> where T : EntityBase
    {

    }
}
